package com.study.crypto.gb.server.service;

import com.study.crypto.dto.gb.RequestAuthenticateDto;
import com.study.crypto.dto.gb.RequestTransferDto;
import com.study.crypto.dto.gb.ResponseAuthenticateDto;
import com.study.crypto.dto.gb.ResponseTransferDto;
import com.study.crypto.gb.server.config.EnvironmentConfig;
import com.study.crypto.signer.Signer;
import com.study.crypto.signer.SignerFactory;
import com.study.crypto.utils.ASN1Utils;
import com.study.crypto.utils.EssPdfUtil;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.asn1.gm.GMObjectIdentifiers;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.pqc.legacy.math.linearalgebra.ByteUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;

/**
 * 状态发布系统服务
 * @author Songjin
 * @since 2021-07-10 19:21
 */
@Transactional(rollbackFor = Exception.class)
@Service
public class PublishService {
    
    private final Signer signer = SignerFactory.produce(GMObjectIdentifiers.sm2sign_with_sm3);
    @Autowired
    private EnvironmentConfig config;
    @Autowired
    private StringRedisTemplate redisTemplate;
    
    /**
     * 电子印章状态推送：数据传输
     * @param request 请求数据
     * @return ResponseTransferDto
     */
    public ResponseTransferDto dataTransfer(RequestTransferDto request) {
        return null;
    }
    
    /**
     * 电子印章状态推送：身份认证
     * @param request 请求数据
     * @return ResponseAuthenticateDto
     * @throws GeneralSecurityException 异常
     * @throws IOException 异常
     * @throws CryptoException 异常
     * @throws CMSException 异常
     */
    public ResponseAuthenticateDto identityAuthenticate(RequestAuthenticateDto request) throws GeneralSecurityException, IOException, CryptoException, CMSException {
        String randomA = request.getRandomA();
        String randomB = EssPdfUtil.genRandomUuid().substring(0, 16);
        String certB = Base64.encodeBase64String(config.getPublishCertification().getCertificate());
        String plaintext = String.format("%s||%s||%s", certB, randomB, randomA);
        byte[] inData = plaintext.getBytes(StandardCharsets.UTF_8);
        byte[] signValue = signer.sign(inData, config.getPublishPrivateKey());
        byte[][] rsArr = ASN1Utils.disassembleSignature(signValue);
        byte[] signature = ByteUtils.concatenate(rsArr[0], rsArr[1]);
        String signBase64 = Base64.encodeBase64String(signature);
        String token = String.format("%s||%s", plaintext, signBase64);
        return new ResponseAuthenticateDto("0", "请求成功", token);
    }
    
}
